package com.wgchao.amc.service.impl;

import com.wgchao.amc.autho.AuthoInfoCenter;
import com.wgchao.amc.common.*;
import com.wgchao.amc.entity.base.*;
import com.wgchao.amc.mapstruct.dto.SysBaseGroupDTO;
import com.wgchao.amc.mapstruct.dto.SysBaseRoleDTO;
import com.wgchao.amc.mapstruct.dto.SysBaseUserDTO;
import com.wgchao.amc.mapstruct.mapper.expand.SysBaseUserMapperExpand;
import com.wgchao.amc.repository.base.*;
import com.wgchao.amc.service.EvaluateService;
import com.wgchao.amc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @ClassName: UserServiceImpl
 * @author: wgchao
 * @createTime: 2019/10/20 12:27 PM
 * @Description: 用户信息管理
 */
@Service
@Transactional
public class UserServiceImpl implements UserService, EvaluateService {
    @Autowired
    private SysBaseUserRepository userRepository;
    @Autowired
    private SysBaseAgencyRepository agencyRepository;
    @Autowired
    private SysBaseUserMapperExpand userMapperExpand;
    @Autowired
    private SysBaseGroupRepository groupRepository;
    @Autowired
    private SysBaseUgRepository ugRepository;
    @Autowired
    private SysBaseRoleRepository roleRepository;
    @Autowired
    private SysBaseUrRepository urRepository;
    @Autowired
    private SysBaseGrRepository grRepository;

    /**
     * 新增用户
     * @param userDTO
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseUserDTO> save(SysBaseUserDTO userDTO, Long userId) throws Exception {
        //数据检校
        EvaluateInfo evaluateInfo = evaluate(userDTO, t -> {
            SysBaseUserDTO tt = (SysBaseUserDTO) t;
            SysBaseUser user = userRepository.findFirstByUname(tt.getUname());
            if(user != null){
                return new EvaluateInfo(false, "账户名已被使用");
            }
            Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(tt.getAgencyCode());
            if(!agencyOptional.isPresent()){
                return new EvaluateInfo(false, "所属机构不存在");
            }
            SysBaseAgency agency = agencyOptional.get();
            if(agency.isCancel()){
                return new EvaluateInfo(false, "所属机构已注销");
            }
            if(agency.isDel()){
                return new EvaluateInfo(false, "所属机构已删除");
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        //开始保存
        SysBaseUser user = userMapperExpand.toEntity(userDTO);
        user.setCancel(false);
        user.setDel(false);
        user.setCreateTime(new Date());
        user.setCreateUser(userId);
        user = userRepository.save(user);

        // 如果选择了部门 保存用户部门关系
        if(userDTO.getGroupInfos() != null && !userDTO.getGroupInfos().isEmpty()){
            List<SysBaseGroupDTO> groupDTOS = userDTO.getGroupInfos();
            List<SysBaseUg> ugList = new ArrayList<>();
            for(SysBaseGroupDTO groupDTO:groupDTOS){
                SysBaseUg ug = ugRepository.findFirstByUserIdAndGroupId(userId, groupDTO.getGroupId());
                if(ug == null){
                    ug = new SysBaseUg();
                    ug.setCreateTime(new Date());
                }
                ug.setUserId(user.getId());
                ug.setGroupId(groupDTO.getGroupId());
                ug.setDel(false);
                ug.setDelTime(null);
                ugList.add(ug);
            }
            ugList = ugRepository.saveAll(ugList);
        }

        userDTO = userMapperExpand.toDTO(user);
        userDTO = userMapperExpand.getCURDUserInfo(userDTO);
        userDTO = userMapperExpand.getAgencyInfo(userDTO);
        userDTO = userMapperExpand.getGroupInfos(userDTO);
        return ResultCommon.success().setData(userDTO);
    }


    /**
     * 查询用户详细信息
     * @param userId 用户ID
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<SysBaseUserDTO> search(Long userId) throws Exception {
        Optional<SysBaseUser> userOptional = userRepository.findById(userId);
        EvaluateInfo evaluateInfo = evaluate(userOptional, u -> {
            Optional<SysBaseUser> e_userOptional = (Optional<SysBaseUser>) u;
            if(!e_userOptional.isPresent()){
                return new EvaluateInfo(false, "用户不存在");
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        SysBaseUser userinfo = userOptional.get();

        SysBaseUserDTO userDTO = userMapperExpand.toDTO(userinfo);
        userDTO = userMapperExpand.getAgencyInfo(userDTO);
        userDTO = userMapperExpand.getCURDUserInfo(userDTO);
        userDTO = userMapperExpand.getGroupInfos(userDTO);
        userDTO = userMapperExpand.getRoleInfos(userDTO);
        return ResultCommon.success().setData(userDTO);
    }

    /**
     *
     * @param agencyCode
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<List<SysBaseUserDTO>> searchOfAgency(String agencyCode) throws Exception {
        Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(agencyCode);
        if(!agencyOptional.isPresent()){
            return ResultCommon.fail("机构不存在");
        }
        SysBaseAgency agency = agencyOptional.get();
        if(agency.isCancel()){
            return ResultCommon.fail("机构已注销");
        }
        if(agency.isDel()){
            return ResultCommon.fail("机构已删除");
        }

        List<SysBaseUser> userList = userRepository.findAllByAgencyCodeAndDelIsFalseAndCancelIsFalse(agencyCode);
        if(userList!=null && !userList.isEmpty()){
            return ResultCommon.success().setData(userMapperExpand.toDTO(userList));
        }
        return ResultCommon.success();
    }

    /**
     * 分页查询用户信息
     * @param page 页码
     * @param limit 条数
     * @param cancel 是否包含注销用户
     * @param del 是否包含删除用户
     * @param agencyCode 机构编号
     * @param userName 用户名称
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<PageData<SysBaseUserDTO>> page(int page, int limit, Boolean cancel, Boolean del, String agencyCode, String userName) throws Exception {
        Specification<SysBaseUser> specification = new Specification<SysBaseUser>() {
            @Override
            public Predicate toPredicate(Root<SysBaseUser> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if(!StringUtils.isEmpty(agencyCode)){
                    Predicate predicate = criteriaBuilder.equal(root.get("agencyCode"), agencyCode);
                    predicateList.add(predicate);
                }
                if(!StringUtils.isEmpty(userName)){
                    Predicate predicate = criteriaBuilder.like(root.get("name"), userName+"%");
                    Predicate predicate1 = criteriaBuilder.equal(root.get("uname"), userName);
                    predicateList.add(criteriaBuilder.or(predicate, predicate1));
                }
                if(cancel != null){
                    if(!cancel){
                        Predicate predicate = criteriaBuilder.isFalse(root.get("cancel"));
                        predicateList.add(predicate);
                    }else{
                        Predicate predicate = criteriaBuilder.isTrue(root.get("cancel"));
                        predicateList.add(predicate);
                    }
                }
                if(del != null){
                    if(!del){
                        Predicate predicate = criteriaBuilder.isFalse(root.get("del"));
                        predicateList.add(predicate);
                    }else{
                        Predicate predicate = criteriaBuilder.isTrue(root.get("del"));
                        predicateList.add(predicate);
                    }
                }
                Predicate[] predicates = new Predicate[predicateList.size()];
                return criteriaBuilder.and(predicateList.toArray(predicates));
            }
        };
        Pageable pageable = PageRequest.of(page-1, limit, Sort.by(Sort.Order.asc("id")));

        Page<SysBaseUser> userPage = userRepository.findAll(specification, pageable);

        List<SysBaseUserDTO> userDTOS = userPage.get().map(sysBaseUser -> {
            SysBaseUserDTO userDTO = userMapperExpand.toDTO(sysBaseUser);
            userDTO = userMapperExpand.getAgencyInfo(userDTO);
            userDTO = userMapperExpand.getCURDUserInfo(userDTO);
            userDTO = userMapperExpand.getGroupInfos(userDTO);
            userDTO = userMapperExpand.getRoleInfos(userDTO);
            return userDTO;
        }).collect(Collectors.toList());

        return ResultCommon.success().setData(new PageData<SysBaseUserDTO>(page, limit,
                Long.valueOf(userPage.getTotalElements()).intValue(), userDTOS));
    }

    /**
     * 更新用户信息
     * @param userDTO 用户信息
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseUserDTO> update(SysBaseUserDTO userDTO, Long userId) throws Exception {
        EvaluateInfo evaluateInfo = evaluate(userDTO, u -> {
            SysBaseUserDTO uDTO = (SysBaseUserDTO) u;
            Optional<SysBaseUser> userOptional = userRepository.findById(uDTO.getId());
            if(!userOptional.isPresent()){
                return new EvaluateInfo(false, "用户不存在");
            }
            SysBaseUser user = userOptional.get();
            if(user.isCancel()){
                return new EvaluateInfo(false, "用户已注销");
            }
            if(user.isDel()){
                return new EvaluateInfo(false, "用户已删除");
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        SysBaseUser user = userMapperExpand.toEntity(userDTO);
        user.setLastUpdateTime(new Date());
        user.setLastUpdateUser(userId);
        user = userRepository.save(user);

        userDTO = userMapperExpand.toDTO(user);
        userDTO = userMapperExpand.getCURDUserInfo(userDTO);
        userDTO = userMapperExpand.getAgencyInfo(userDTO);
        userDTO = userMapperExpand.getGroupInfos(userDTO);
        return ResultCommon.success().setData(userDTO);
    }

    /**
     * 删除用户信息
     * @param userIds 用户ID数组
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon deletes(List<Long> userIds, Long userId) throws Exception {
        List<SysBaseUser> users = new ArrayList<>();
        for(Long id : userIds){
            Optional<SysBaseUser> userOptional = userRepository.findById(id);
            EvaluateInfo evaluateInfo = evaluate(userOptional, u -> {
                Optional<SysBaseUser> e_userOptional = (Optional<SysBaseUser>) u;
                if(!e_userOptional.isPresent()){
                    return new EvaluateInfo(false, id+"用户不存在");
                }
                return new EvaluateInfo(true, null);
            });
            if(!evaluateInfo.isSuccess()){
                return ResultCommon.fail(evaluateInfo.getMsg());
            }
            SysBaseUser user = userOptional.get();
            user.setDel(true);
            user.setDelTime(new Date());
            user.setDelUser(userId);
            users.add(user);
        }

        userRepository.deleteAll(users);

        return ResultCommon.success();
    }

    /**
     * 注销用户信息
     * @param userId 用户ID
     * @param status 注销？解除注销状态
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon cancel(Long userId, boolean status, Long auserId) throws Exception {
        Optional<SysBaseUser> userOptional = userRepository.findById(userId);
        EvaluateInfo evaluateInfo = evaluate(userOptional, u -> {
            Optional<SysBaseUser> e_userOptional = (Optional<SysBaseUser>) u;
            if(!e_userOptional.isPresent()){
                return new EvaluateInfo(false, "用户不存在");
            }
            SysBaseUser user = e_userOptional.get();
            if(user.isDel()){
                return new EvaluateInfo(false, "用户已删除");
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        SysBaseUser user = userOptional.get();
        user.setCancel(status);
        user.setLastUpdateUser(auserId);
        user.setLastUpdateTime(new Date());
        user = userRepository.save(user);

        return ResultCommon.success().setMsg("用户注销状态已修改");
    }



    /****************************************************/

    /**
     *  为用户分配部门
     * @param userId 用户ID
     * @param groupDTOS 部门列表
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseUserDTO> assignedGroup(Long userId, List<SysBaseGroupDTO> groupDTOS) throws Exception {
        EvaluateInfo evaluateInfo = evaluate(groupDTOS, groups -> {
            Optional<SysBaseUser> userOptional = userRepository.findById(userId);
            if(!userOptional.isPresent()){
                return new EvaluateInfo(false, "用户不存在");
            }
            SysBaseUser user = userOptional.get();
            if(user.isCancel()){
                return new EvaluateInfo(false, "用户已注销");
            }
            if(user.isDel()){
                return new EvaluateInfo(false, "用户已删除");
            }
            if(groupDTOS==null || groupDTOS.isEmpty()){
                return new EvaluateInfo(false, "用户归属部门不能为空");
            }
            for(SysBaseGroupDTO groupDTO:groupDTOS){
                Optional<SysBaseGroup> groupOptional = groupRepository.findById(groupDTO.getGroupId());
                if(!groupOptional.isPresent()){
                    return new EvaluateInfo(false, groupDTO.getGroupId()+"部门不存在");
                }
                SysBaseGroup group = groupOptional.get();
                if(group.isDel()){
                    return new EvaluateInfo(false, groupDTO.getGroupId()+"部门已删除");
                }
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        //将原有的归属部门全部删除
        ugRepository.updateUGToDel(new Date(), userId);

        //添加新的归属部门 如果已经存在 则更新为未删除
        List<SysBaseUg> ugList = new ArrayList<>();
        for(SysBaseGroupDTO groupDTO:groupDTOS){
            SysBaseUg ug = ugRepository.findFirstByUserIdAndGroupId(userId, groupDTO.getGroupId());
            if(ug == null){
                ug = new SysBaseUg();
                ug.setCreateTime(new Date());
            }
            ug.setUserId(userId);
            ug.setGroupId(groupDTO.getGroupId());
            ug.setDel(false);
            ug.setDelTime(null);
            ugList.add(ug);
        }
        ugList = ugRepository.saveAll(ugList);

        Optional<SysBaseUser> userOptional = userRepository.findById(userId);
        SysBaseUserDTO userDTO = userMapperExpand.toDTO(userOptional.get());
        userDTO = userMapperExpand.getCURDUserInfo(userDTO);
        userDTO = userMapperExpand.getAgencyInfo(userDTO);
        userDTO = userMapperExpand.getGroupInfos(userDTO);
        return ResultCommon.success().setData(userDTO);
    }


    /**
     * 为用户分配角色
     * @param userId 用户ID
     * @param roleDTOS 角色列表
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseUserDTO> assignedRoles(Long userId, Long groupId, List<SysBaseRoleDTO> roleDTOS) throws Exception {
        EvaluateInfo evaluateInfo = evaluate(roleDTOS, roleDtos -> {
            List<SysBaseRoleDTO> roleDTOS1 = (List<SysBaseRoleDTO>) roleDtos;
            Optional<SysBaseUser> userOptional = userRepository.findById(userId);
            if(!userOptional.isPresent()){
                return new EvaluateInfo(false, "用户不存在");
            }
            SysBaseUser user = userOptional.get();
            if(user.isDel()){
                return new EvaluateInfo(false, "用户已删除");
            }
            if(user.isCancel()){
                return new EvaluateInfo(false, "用户已注销");
            }
            Optional<SysBaseGroup> groupOptional = groupRepository.findById(groupId);
            if(!groupOptional.isPresent()){
                return new EvaluateInfo(false, "部门不存在");
            }
            SysBaseGroup group = groupOptional.get();
            if(group.isDel()){
                return new EvaluateInfo(false, "部门已删除");
            }
            SysBaseUg ug = ugRepository.findFirstByUserIdAndGroupIdAndDelIsFalse(userId, groupId);
            if(ug == null){
                return new EvaluateInfo(false, "用户不属于该部门");
            }
            for(SysBaseRoleDTO roleDTO:roleDTOS1){
                Optional<SysBaseRole> roleOptional = roleRepository.findById(roleDTO.getId());
                if(!roleOptional.isPresent()) {
                    return new EvaluateInfo(false, "角色不存在");
                }
                SysBaseRole role = roleOptional.get();
                if(role.isDel()){
                    return new EvaluateInfo(false, "角色已删除");
                }
                role = roleRepository.findRoleByUG(roleDTO.getId(), userId);
                if(role == null){
                    return new EvaluateInfo(false, "角色不属于用户所在部门");
                }
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        //将用户的全部角色置为删除状态
        urRepository.updateUrToDel(userId, groupId, new Date());

        //为用户重新分配角色
        for(SysBaseRoleDTO roleDTO:roleDTOS){
            SysBaseUr ur = urRepository.findFirstByUserIdAndRoleIdAndGroupId(userId, roleDTO.getId(), groupId);
            if(ur == null){
                ur = new SysBaseUr();
            }
            ur.setRoleId(roleDTO.getId());
            ur.setGroupId(groupId);
            ur.setUserId(userId);
            ur.setCreateTime(new Date());
            ur.setDel(false);
            ur.setDelTime(null);
            ur = urRepository.save(ur);
        }

        Optional<SysBaseUser> userOptional = userRepository.findById(userId);
        SysBaseUserDTO userDTO = userMapperExpand.toDTO(userOptional.get());
        userDTO = userMapperExpand.getRoleInfos(userDTO);
        return ResultCommon.success().setData(userDTO);
    }


    /**
     * 登入 获取token
     * @param uname
     * @param password
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<String> in(String uname, String password) throws Exception {
        SysBaseUser user = userRepository.findFirstByUname(uname);
        if(user == null){
            return ResultCommon.fail("账户不存在");
        }
        if(user.isCancel()){
            return ResultCommon.fail("账户已注销");
        }
        if(user.isDel()){
            return ResultCommon.fail("账户已删除");
        }
        if(password.equals(user.getPassword())){
            return ResultCommon.success().setData(JWTUtil.createToken(user.getId()+""));
        }
        return ResultCommon.fail("账户密码不匹配");
    }
}
